
//在Flutter3.0之后SchedulerBinding.instance就不是一个可空类型了,为了兼容3.0之前使用此方法
//https://docs.flutter.dev/development/tools/sdk/release-notes/release-notes-3.0.0

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

// 创建一个单例用来管理这个Overlay
class LoadingView {
  static final LoadingView instance = LoadingView._internal();

  factory LoadingView() {
    return instance;
  }

  LoadingView._internal();

  CustomOverlayEntry? entry;
  Widget? widget;

  static TransitionBuilder builder({
    TransitionBuilder? builder,
  }) {
    return (BuildContext context, Widget? child) {
      if (builder != null) {
        return builder(context, CustomLoading(child: child));
      } else {
        return CustomLoading(child: child);
      }
    };
  }

  static void show() {
    instance.widget = Center(
      child: Container(
        // color: Colors.clear,
        width: 60,
        height: 60,
        padding: const EdgeInsets.all(10),
        child: const CircularProgressIndicator(
          valueColor: AlwaysStoppedAnimation(Color(0xff2E50FF)),
        ),
      ),
    );
    instance.entry?.markNeedsBuild();
  }

  static void dismiss() {
    instance.widget = null;
    instance.entry?.markNeedsBuild();
  }
}

T? _ambiguate<T>(T? value) => value;
// 定义 一个OverlayEntry
class CustomOverlayEntry extends OverlayEntry{
  @override
  CustomOverlayEntry({
    required WidgetBuilder builder,
  }) : super(builder: builder);

  @override
  void markNeedsBuild() {
    //为了保证不在build阶段刷新OverlayEntry,具体的可阅读一下这篇文章
    // https://book.flutterchina.club/chapter14/flutter_app_startup.html
    if (_ambiguate(SchedulerBinding.instance)!.schedulerPhase ==
        SchedulerPhase.persistentCallbacks) {
      _ambiguate(SchedulerBinding.instance)!.addPostFrameCallback((_) {
        super.markNeedsBuild();
      });
    } else {
      super.markNeedsBuild();
    }
  }
}

// 创建一个Overlay，通过MaterialApp的builder 方法,使能包裹住页面。
class CustomLoading extends StatefulWidget {
  final Widget? child;

  const CustomLoading({Key? key, required this.child}) : super(key: key);

  @override
  State<CustomLoading> createState() => _CustomLoadingState();
}

class _CustomLoadingState extends State<CustomLoading> {
  late CustomOverlayEntry _entry;

  @override
  void initState() {
    super.initState();
    _entry = CustomOverlayEntry(
        builder: (_) => LoadingView.instance.widget ?? Container());
    LoadingView.instance.entry = _entry;
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Overlay(
        initialEntries: [
          CustomOverlayEntry(
            builder: (BuildContext context) {
              if (widget.child != null) {
                return widget.child!;
              } else {
                return Container();
              }
            },
          ),
          _entry,
        ],
      ),
    );
  }
}